package com.liveneo.system.base.utils;

import java.io.UnsupportedEncodingException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import org.apache.commons.codec.binary.Base64;
import com.fasterxml.jackson.annotation.JsonInclude.Include;
import com.fasterxml.jackson.core.JsonParser.Feature;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.liveneo.adapter.base.support.LogUtils;

/**
 * @Desc：Json工具类
 * @Title：JsonUtils
 * @address: http://www.liveneo.com.cn/
 * @author: zhaoyy
 * @version: 1.0 
 * @date: 2016年11月24日 下午5:20:38
 */
public class JacksonUtils {
    private final static ObjectMapper objectMapper = new ObjectMapper();

    public static ObjectMapper getInstance() {
        // 设置输入时忽略JSON字符串中存在而Java对象实际没有的属性
        objectMapper.setSerializationInclusion(Include.NON_NULL);
        objectMapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
        objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
        objectMapper.configure(Feature.ALLOW_SINGLE_QUOTES, true);// 设置可用单引号
        objectMapper.configure(Feature.ALLOW_UNQUOTED_FIELD_NAMES, true);// 设置字段可以不用双引号包括
        objectMapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"));// 设置时间格式
        objectMapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);// 设置实体无属性和json串属性对应时不会出错
        return objectMapper;
    }

    /**
     * javaBean,list,array convert to json string
     */
    public static String obj2json(Object obj) throws Exception {
        objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
        return objectMapper.writeValueAsString(obj);
    }

    /**
     * json string convert to javaBean
     */
    public static <T> T json2pojo(String jsonStr, Class<T> clazz) throws Exception {
        objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
        return objectMapper.readValue(jsonStr, clazz);
    }

    /**
     * json string convert to map
     */
    public static <T> Map<String, Object> json2map(String jsonStr) throws Exception {
        return objectMapper.readValue(jsonStr, Map.class);
    }

    /**
     * json string convert to map with javaBean
     */
    public static <T> Map<String, T> json2map(String jsonStr, Class<T> clazz) throws Exception {
        Map<String, Map<String, Object>> map = objectMapper.readValue(jsonStr, new TypeReference<Map<String, T>>() {
        });
        Map<String, T> result = new HashMap<String, T>();
        for (Entry<String, Map<String, Object>> entry : map.entrySet()) {
            result.put(entry.getKey(), map2pojo(entry.getValue(), clazz));
        }
        return result;
    }

    /**
     * json array string convert to list with javaBean
     */
    public static <T> List<T> json2list(String jsonArrayStr, Class<T> clazz) throws Exception {
        List<Map<String, Object>> list = objectMapper.readValue(jsonArrayStr, new TypeReference<List<T>>() {
        });
        List<T> result = new ArrayList<T>();
        for (Map<String, Object> map : list) {
            result.add(map2pojo(map, clazz));
        }
        return result;
    }

    /**
     * map convert to javaBean
     */
    public static <T> T map2pojo(Map map, Class<T> clazz) {
        return objectMapper.convertValue(map, clazz);
    }

    /**
     * 对象转换为base64加密字符串
     * @param enc  使用编码
     * @return 对象的json的base64加密串
     * @throws Exception 
     * @throws UnsupportedEncodingException
     */
    public static String toJsonWithBase64(Object obj, String enc) throws Exception {
        // 对象转换成Json字符串
        String jsonStr = JacksonUtils.obj2json(obj);
        String jsonStrWithBase64 = null;
        try {
            // base64加密
            jsonStrWithBase64 = Base64.encodeBase64String(jsonStr.getBytes(enc));
        } catch (UnsupportedEncodingException e) {
            throw new RuntimeException(e);
        }
        return jsonStrWithBase64;
    }

    /**
     * base64加密字符串转换为对象
     * @param enc  使用编码
     * @return 对象的json的base64加密串
     * @throws Exception 
     * @throws UnsupportedEncodingException
     */
    public static <T> T fromJsonWithBase64(String base64JsonData, Class<T> type, String enc) throws Exception {
        // 对象转换成Json字符串
        String jsonStrWithBase64 = null;
        try {
            // base64解密
            jsonStrWithBase64 = new String(Base64.decodeBase64(base64JsonData.getBytes(enc)), enc);
            LogUtils.info("接收报文信息【" + jsonStrWithBase64 + "】");
        } catch (UnsupportedEncodingException e) {
            throw new RuntimeException(e);
        }
        T obj = JacksonUtils.json2pojo(jsonStrWithBase64, type);
        return obj;
    }
    /**
     * 对象转换为base64加密字符串（使用UTF-8编码）
     * @return 对象的json的base64加密串
     * @throws UnsupportedEncodingException
     */
    // public static String toJsonWithBase64(Object obj) {
    // return JsonUtils.toJsonWithBase64(obj, "UTF-8");
    // }
    /**
     * base64加密字符串转换为对象（使用UTF-8编码）
     * @return 对象的json的base64加密串
     * @throws UnsupportedEncodingException
     */
    // public static <T> T fromJsonWithBase64(String base64JsonData, Class<T> type) {
    // return JsonUtils.fromJsonWithBase64(base64JsonData, type, "UTF-8");
    // }
}
